package com.zhentao.service.impl;


import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhentao.file.service.FileStorageService;
import com.zhentao.mapper.CdzInviteRecordMapper;
import com.zhentao.mapper.CdzUserIncomeMapper;
import com.zhentao.mapper.UsersMapper;
import com.zhentao.model.common.dtos.ResponseResult;
import com.zhentao.model.common.enums.AppHttpCodeEnum;
import com.zhentao.model.common.pojo.dto.UsersDto;
import com.zhentao.model.common.pojo.income.CdzInviteRecord;
import com.zhentao.model.common.pojo.income.CdzUserIncome;
import com.zhentao.model.common.pojo.users.MassageParam;
import com.zhentao.model.common.pojo.users.Users;
import com.zhentao.model.common.pojo.users.param.Param;
import com.zhentao.model.common.pojo.users.param.UserBalanceParam;
import com.zhentao.service.IUsersService;
import com.zhentao.userLocal.UserThreadLocalUtil;
import lombok.SneakyThrows;
import org.mindrot.jbcrypt.BCrypt;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import utils.ChargeAliyunMsgUtils;
import utils.JwtService;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;

import static com.zhentao.model.common.enums.AppHttpCodeEnum.PARAM_REQUIRE;
import static com.zhentao.model.common.enums.AppHttpCodeEnum.SUCCESS;
import static com.zhentao.user.UserCommon.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author mp
 * @since 2024-12-17
 */
@Service
// 该类是服务层实现类，继承了ServiceImpl并且实现了IUsersService接口，用于处理用户相关业务逻辑
public class UsersServiceImpl extends ServiceImpl<UsersMapper, Users> implements IUsersService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private UsersMapper usersMapper;
    @Autowired
    private CdzUserIncomeMapper cdzUserIncomeMapper;
    @Autowired
    private CdzInviteRecordMapper cdzInviteRecordMapper;
@Autowired
private FileStorageService fileStorageService;
    @Override
    // 实现登录方法，处理用户登录业务逻辑
    public ResponseResult login(UsersDto usersDto) {
        if (usersDto.getLoginType() == 0) {
            // 判断用户名或密码是否为空，如果为空则返回错误提示
            if (usersDto == null || usersDto.getPassword() == null) {
                return ResponseResult.errorResult(400, "清 先输入");
            }

            // 创建查询条件包装器，用于按用户名查询用户信息
            LambdaQueryWrapper<Users> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(Users::getUserName, usersDto.getUserName());
            // 根据条件查询出单个用户信息
            Users one = this.getOne(wrapper);

            // 如果没查询到用户，返回账号和密码不匹配的错误提示
            if (one == null) {
                return ResponseResult.errorResult(400, "账号和密码不匹配");
            }
            if (one.getStatus().equals(0)) {
                return ResponseResult.errorResult(400, "账号被冻结");
            }
            boolean passwordMatches = BCrypt.checkpw(usersDto.getPassword(), one.getPassword());
            // 如果密码不相等，返回账号和密码是否正确的错误提示
            if (!passwordMatches) {
                return ResponseResult.errorResult(400, "账号和密码是否正确");
            }
            String token = createToken(one);

            // 返回包含token的成功结果
            return ResponseResult.okResult(token);
        }

        if (usersDto.getLoginType() == 2) {
            String phone = usersDto.getPhone();
            if (phone == null) {
                return ResponseResult.errorResult(400, "请输入手机号");
            }
            if (phone.length() != 11) {
                return ResponseResult.errorResult(400, "请输入正确的手机号");
            }
            //查询用户
            Users users = usersMapper.selectOne(new LambdaQueryWrapper<Users>().eq(Users::getPhone, phone));
            if (users == null) {
                return ResponseResult.errorResult(400, "该手机号未注册");
            }
            if (usersDto.getCode() == null) {
                return ResponseResult.errorResult(400, "请输入验证码");
            }
            // 获取验证码
            String s = redisTemplate.opsForValue().get(CHARGE_USER_MASSAGE_CODE_KEY);
            // 验证码错误
            if (!Objects.equals(usersDto.getCode(), s)) {
                return ResponseResult.errorResult(400, "验证码错误");
            }
            String token = createToken(users);
            return ResponseResult.okResult(token);
        }
        return ResponseResult.okResult(SUCCESS);
    }

    private static String createToken(Users one) {
        // 创建一个Map用于存放要生成token所需的数据
        Map<String, Object> map = new HashMap<>();
        // 获取登录用户的id并存入map
        Long id = one.getId();
        map.put("userId", id);
        // 打印用户id，方便查看（可根据实际需求调整）
        System.out.println(id + "------------------------------");
        // 将用户名存入map
        map.put("username", one.getUserName());
        map.put("nickname", one.getNickName());
        // 调用JwtService的createToken方法生成token


        String token = JwtService.createToken(map);
        return token;
    }

    //编辑用户信息
    @Override
    public ResponseResult updateusers(Param param) {
        Long id = UserThreadLocalUtil.getUser();
        boolean flag=false;
        // 检查参数是否有效
        if (param == null) {
            return ResponseResult.errorResult(PARAM_REQUIRE);
        }

        // 查询当前昵称是否已经被使用
        Users existingUser = getOne(Wrappers.<Users>lambdaQuery().eq(StringUtils.checkValNotNull(param.getNickName()),Users::getNickName,param.getNickName()));
        if (existingUser != null) {
            return ResponseResult.errorResult(400, "该昵称已被使用");
        }
String imgPath=redisTemplate.opsForValue().get(CHARGE_USER_REDIS_PREFIX_AVATAR_IMG);
        if(imgPath==null){
//            如果图片为空说明没有对头像进行修改
            Users users1=new Users();
            users1.setId(id);
            users1.setNickName(param.getNickName());
            flag=updateById(users1);
            return flag?ResponseResult.okResult(SUCCESS):ResponseResult.errorResult(400,"修改失败");
        }
        Users users1=new Users();
        users1.setId(id);
        users1.setNickName(param.getNickName());
        users1.setAvatarUrl(imgPath);
        flag=updateById(users1);
        return flag?ResponseResult.okResult(SUCCESS):ResponseResult.errorResult(400,"修改失败");
    }
//gen
    @Override
    public ResponseResult selectbyid() {
        Long id = UserThreadLocalUtil.getUser();
        Users byId = this.getById(id);
        return ResponseResult.okResult(byId);
    }

    @Override
    public ResponseResult messageCode(MassageParam param) {
//        判断参数是否有效
        if (param == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
//        创建随机数
        String s = RandomUtil.randomNumbers(6);
        redisTemplate.opsForValue().set(CHARGE_USER_MASSAGE_CODE_KEY, s);
        redisTemplate.expire(CHARGE_USER_MASSAGE_CODE_KEY, CHARGE_USER_MASSAGE_CODE_EXPIRE, TimeUnit.MINUTES);
        param.setCode(s);
        param.setExpireTime(5L);
        ChargeAliyunMsgUtils.sendMsg(param.getPhone(), Integer.valueOf(param.getCode()), param.getExpireTime());
        return ResponseResult.errorResult(SUCCESS);
    }


    @Override
    public ResponseResult regist(Users users) {

        // 随机生成一个6位数的26英文字母大写的邀请码
        String inviteCode = RandomUtil.randomString("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 6);
        System.out.println("生成的邀请码: " + inviteCode);

        // 获取用户输入的邀请码
        String invitedCode = users.getInvitedCode(); // 获取用户输入的邀请码
        Long inviterId = null;  // 用于存储邀请人ID

        if (invitedCode != null && !invitedCode.isEmpty()) {
            // 查询数据库中是否存在该邀请码的用户（邀请人）
            Users existingUser = usersMapper.selectOne(Wrappers.<Users>lambdaQuery().eq(Users::getInviteCode, invitedCode));
            if (existingUser == null) {
                return ResponseResult.errorResult(400, "注册失败，邀请码无效");
            }

            // 获取邀请人的 ID
            inviterId = existingUser.getId(); // 假设 ID 是 Long 类型
        }

        // 设置邀请码
        users.setInviteCode(inviteCode);
        // 设置昵称与用户名相同
        users.setNickName(users.getUserName());
        users.setPoint("0");
        users.setYhj("0");

        // 使用 BCrypt 对密码进行加密
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodedPassword = passwordEncoder.encode(users.getPassword());
        users.setPassword(encodedPassword);  // 设置加密后的密码

        // 插入用户
        boolean save = this.save(users);
        if (save) {
            System.out.println("用户插入成功，影响的行数：" + save);
            // 获取插入后的用户 ID
            Long newUserId = users.getId();
            System.out.println("插入后的用户ID: " + newUserId);

            // 如果邀请码有效，保存邀请人 ID 到 CdzUserIncome 表
            if (inviterId != null) {
                // 创建并保存 CdzUserIncome 记录
                CdzUserIncome cdzUserIncome = new CdzUserIncome();
                CdzInviteRecord cdzInviteRecord = new CdzInviteRecord();
                cdzUserIncome.setUserId(inviterId);  // 设置邀请人ID
                cdzUserIncome.setType("邀请获得");
                cdzUserIncome.setIncome(Double.valueOf(10.00));
                cdzUserIncome.setCreateTime(new Date());
                //    创建并保存 cdzInviteRecord 记录
                cdzInviteRecord.setInviteUserId(inviterId);
                cdzInviteRecord.setInvitedUserId(newUserId);
                cdzInviteRecord.setNotes("无备注");
                cdzInviteRecord.setInvitedTime(new Date());
                // 可以根据需要设置其他字段
                cdzUserIncomeMapper.insert(cdzUserIncome);
                cdzInviteRecordMapper.insert(cdzInviteRecord);
            }



            return ResponseResult.okResult("注册成功");
        } else {
            System.out.println("用户注册失败");
            return ResponseResult.errorResult(401);
        }
    }





    @SneakyThrows
    @Override
    public ResponseResult uploadAvatarImg(MultipartFile file) {
        // 先清除redis原有的头像地址
        redisTemplate.delete(CHARGE_USER_REDIS_PREFIX_AVATAR_IMG);
        // 头像处理
        String uuid = UUID.randomUUID().toString(true);
        String path = fileStorageService.uploadImgFile(CHARGE_USER_AVATAR_PREFIX, uuid + ".jpg", file.getInputStream());
        // 存储新的头像地址
        redisTemplate.opsForValue().set(CHARGE_USER_REDIS_PREFIX_AVATAR_IMG, path);
        // 设置过期时间
        redisTemplate.expire(CHARGE_USER_REDIS_PREFIX_AVATAR_IMG,60L, TimeUnit.SECONDS);

        return ResponseResult.okResult(200000,path);
    }
//退出登录
    @Override
    public ResponseResult userlogout() {
        Long id = UserThreadLocalUtil.getUser();
//        清空缓存中的用户
        Boolean delete = redisTemplate.delete("CHARGE_USER_LOGIN_KEY" + id);
        return delete?ResponseResult.okResult(200000,"登出成功"):ResponseResult.errorResult(400,"登出失败");
    }


    /**
     * 检查邀请码是否已存在
     *
     * @param inviteCode 邀请码
     * @return true 表示已存在，false 表示不存在
     */
    private boolean isInviteCodeExist(String inviteCode) {
        // 这里需要调用你的数据库查询方法，检查邀请码是否存在
        // 假设你有一个 `userMapper` 用来执行数据库查询
        // 你可以根据实际情况修改这段代码
        int count = usersMapper.countByInviteCode(inviteCode);  // 假设存在这个方法
        return count > 0;  // 如果返回的 count 大于 0，则表示邀请码已经存在
    }

    @Override
    public ResponseResult updateBalance(UserBalanceParam userBalanceParam) {
//            获取用户对象
        Users users = this.getById(userBalanceParam.getUserId());
        //获取用户余额
        Double balance = users.getBalance();
        //获取用户优惠卷数量
        Integer yhj = Integer.valueOf(users.getYhj());
        //减去用户优惠卷数量
        if (userBalanceParam.getCouponMount() > yhj) {
            return ResponseResult.errorResult(400, "优惠卷数量不足");
        }
        yhj -= userBalanceParam.getCouponMount();
            // 充值
            if (userBalanceParam.getOrderType() == 1) {
                balance += userBalanceParam.getAmount();
//            减去用户优惠卷数量
                users.setYhj(String.valueOf(yhj));
//            增加用户余额
                users.setBalance(balance);
                this.updateById(users);
                return ResponseResult.okResult(200, "充值成功");
            }else {
                //判断是否使用余额支付
                if (!userBalanceParam.getChannelId().equals("9")) {
                    //使用支付宝进行支付，不需要减去用户的余额，只需要减去优惠卷数量即可
                    //            减去用户优惠卷数量
                    users.setYhj(String.valueOf(yhj));
                    this.updateById(users);
                    return ResponseResult.okResult(200, "支付成功");
                }else{
                    //减去用户余额
                    balance -= userBalanceParam.getAmount();
                    users.setBalance(balance);
                    users.setYhj(String.valueOf(yhj));
                    this.updateById(users);
                    return ResponseResult.okResult(200, "支付成功");
                }
            }
        }



    @Override
    public ResponseResult updatePonit(UserBalanceParam userBalanceParam) {
        Users users = this.getById(userBalanceParam.getUserId());
        Integer point = userBalanceParam.getPoint();
        // 用户当前积分减去获得的积分
        Integer point1 = Integer.valueOf(users.getPoint());
        point1 -= point;
        users.setPoint(String.valueOf(point1));
        // 增加用户的优惠卷数量
        int yhj = Integer.parseInt(users.getYhj());
        users.setYhj((yhj+1)+"");
        boolean b = this.updateById(users);
        if (b) {
            return ResponseResult.okResult(200, "积分兑换成功");
        }else {
            return ResponseResult.errorResult(400, "积分兑换失败");
        }
    }


}





